/*****************************
 *@file: BaseCharacter
 *@author: 陈吕唐
 *@desc: 基础角色
 *@date: 2024-03-16	13:39
 *****************************/
import { _decorator, Component, warn } from 'cc';
import IBaseBuffDTO from './buff/IBaseBuffDTO';
import IBaseBulletValue from './bullet/IBaseBulletValue';
import IBaseAttribute from './character/IBaseAttribute';
import IFightAttribute from './character/IFightAttribute';
import { CharacterEvent } from './CharacterEvent';
const { ccclass, property, disallowMultiple, executionOrder } = _decorator;


@ccclass('BaseCharacter')
@disallowMultiple(true)
@executionOrder(0)
export class BaseCharacter extends Component implements IBaseAttribute, IFightAttribute {
    /****************************************************************************************************************
     *Readonly 常量
     ****************************************************************************************************************/
    /**
     * 路程长度
     */
    protected static readonly DIST_LENGTH = 3;
    /****************************************************************************************************************
    *Property 定义变量
    ****************************************************************************************************************/
    /**************************************
     * 状态
     *************************************/
    /**
     * 是否在游戏中 未开始/死亡结算时 为false
     */
    public gameIng: boolean = false;
    /**************************************
    * 基础属性
    *************************************/
    private _hp: number = 0;

    private _atk: number = 0;

    private _def: number = 0;

    private _spd: number = 0;

    private _maxHp: number = 0;
    /**************************************
     * 战斗属性
     *************************************/
    /**
     * 护盾值(抵消受到的伤害)
     */
    private _shield: number = 0;


    /**
     * 易伤(自身受到的伤害增加)
     */
    private _easy: number = 0;


    /**
     * 减伤(减少受到的伤害[0-1])
     */
    private _reduce: number = 0;


    /**
     * 增伤(造成的伤害增加)
     */
    private _boost: number = 0;

    /**
     * 加速(攻击速度加成)
     */
    private _speedUp: number = 0;


    /**
     * 攻击力(攻击力增加)
     */
    private _attackUp: number = 0;
    /***************************************************************
    * 
    ***************************************************************/
    /**
     * 当前可以攻击的对象
     */
    public enemySet: Set<BaseCharacter> = new Set();
    /***************************************************************
    * 行动相关
    ***************************************************************/
    /**
     * 距离下次行动间隔(归零时开始行动)
     */
    private _dist: number = 0;
    /***************************************************************
    *PropertyUI 引用的控件
    ***************************************************************/
    /****************************************************************************************************************
     * Lifecycle 生命周期相关方法
     ****************************************************************************************************************/
    protected onLoad(): void {

    }

    protected onEnable(): void {

    }

    protected lateUpdate(dt: number): void {

        // if (GameSingle.stopGame) {
        //     return;
        // }

        if (!this.gameIng) {
            return;
        }
        this.dist -= dt * this.spd * (1 + this.speedUp);
    }

    protected onDisable(): void {

    }

    protected onDestroy(): void {

    }
    /****************************************************************************************************************
     * Public 公有方法
     ****************************************************************************************************************/
    /****************************************
     * 对象池
     ***************************************/
    /**
     * 对象池回收时调用
     */
    public unuse() {
        this.gameIng = false;
        this._shield = 0;
        this._easy = 0;
        this._reduce = 0;
        this._boost = 0;
        this._speedUp = 0;
        this._attackUp = 0;
    }

    /**
     * 对象池重新启用时调用
     */
    public reuse(values: any[]) {

    }
    /****************************************
     * 
     ***************************************/
    /**
     * 初始化数据
     * @param value 
     */
    public init(value: IBaseAttribute) {
        this._hp = value.hp;
        this._atk = value.atk;
        this._def = value.def;
        this._spd = value.spd;
        this._maxHp = value.hp;
    }

    /**
     * 开始游戏(角色开始行动)
     */
    public startGame() {
        this.gameIng = true;
        this.node.emit(CharacterEvent.START);
    }


    /**
     * 计算当前普通攻击伤害
     * @returns 
     */
    public normalDamage(): number {
        let value = this.atk * (1 + this.boost);
        value = Math.floor(value);
        return value;
    }

    /**
     * 受到伤害
     * @param bullet 子弹数据
     * @param source 伤害来源
     * @returns 最终数值伤害
     */
    public takeDamage(bullet: IBaseBulletValue, source: BaseCharacter = undefined): number {

        if (!this.gameIng) {
            warn(`角色未开始行动或已死亡，无法受到伤害`);
            return 0;
        }

        if (!bullet) {
            warn(`子弹数据为空`);
            return 0;
        }

        let damage = bullet.value;
        /**
         * 计算伤害
         */
        damage = (damage - this.def) * (1 + this.easy) * (1 - this.reduce);

        /**
         * 护盾抵消
         */
        if (this.shield >= damage) {
            this.shield -= damage;
            damage = 0;
        } else {
            damage -= this.shield;
            this.shield = 0;
        }

        /**
         * 伤害不能为负数
         */
        damage = Math.max(damage, 0);
        /**
         * 扣除血量
         */
        this.hp -= damage;

        /**
         * 伤害回调,(将伤害结果通知攻击者)
         */
        if (source) {
            source.backDamage(damage, this);
        }

        return damage;
    }


    /**
     * 成功造成伤害后返回方法
     * @param value 返回的伤害结果
     * @param def 被攻击对象
     */
    public backDamage(value: number, def: BaseCharacter) {
        /**
         * 成功击杀敌人
         */
        if (def && !def.gameIng) {
            this.node.emit(CharacterEvent.KILL);
        }
    }


    /**
     * 添加buff
     * @param value 
     */
    public addBuff(value: IBaseBuffDTO) {
        if (!this.gameIng) {
            return;
        }

        // let control = this.node.getComponent(BuffController);
        // if (!control) {

        // }
    }
    /****************************************************************************************************************
     * private 私有方法
     ****************************************************************************************************************/
    /**
     * 血量变动后调用
     * @param value 
     */
    protected updateHp(value: number): void {
        this.node.emit(CharacterEvent.UPDATE_HP, value);

        /**
         * 死亡判断
         */
        if (value <= 0) {
            this.dead();
        }
    }


    /**
     * 角色行动逻辑
     */
    protected characterAction() {
        // if (DEBUG) {
        //     console.log(`开始行动`)
        // }
        this.dist = BaseCharacter.DIST_LENGTH;
        if (this.gameIng) {
            this.node.emit(CharacterEvent.ACTION);
        }
    }

    /**
     * 死亡后调用
     */
    protected dead(): void {
        this.gameIng = false;
        this.node.emit(CharacterEvent.DEAD);
    }
    /****************************************************************************************************************
     * Property Get && Set 属性的 get && set 函数
     ****************************************************************************************************************/
    public get hp(): number {
        return this._hp;
    }
    public set hp(value: number) {
        if (value == this.hp) {
            return;
        }
        this._hp = value;
        this.updateHp(value);
    }
    public get atk(): number {
        return this._atk;
    }
    public set atk(value: number) {
        this._atk = value;
    }
    public get def(): number {
        return this._def;
    }
    public set def(value: number) {
        this._def = value;
    }
    public get spd(): number {
        return this._spd;
    }
    public set spd(value: number) {
        this._spd = value;
    }
    public get maxHp(): number {
        return this._maxHp;
    }
    /**************************************
     * 战斗属性
     *************************************/
    public get shield(): number {
        return this._shield;
    }
    public set shield(value: number) {
        this._shield = value;
    }
    public get easy(): number {
        return this._easy;
    }
    public set easy(value: number) {
        this._easy = value;
    }
    public get reduce(): number {
        return this._reduce;
    }
    public set reduce(value: number) {
        this._reduce = value;
    }
    public get boost(): number {
        return this._boost;
    }
    public set boost(value: number) {
        this._boost = value;
    }
    public get speedUp(): number {
        return this._speedUp;
    }
    public set speedUp(value: number) {
        this._speedUp = value;
    }
    public get attackUp(): number {
        return this._attackUp;
    }
    public set attackUp(value: number) {
        this._attackUp = value;
    }
    /**************************************
     * 行动属性
     *************************************/
    public get dist(): number {
        return this._dist;
    }
    public set dist(value: number) {
        if (value < 0) {
            value = 0;
        }
        this._dist = value;
        if (value <= 0) {
            this.characterAction();
        }
    }
}

